//
//  Emoticon.swift
//  Emoticon_Keyboard
//
//  Created by 杨振 on 15/10/17.
//  Copyright © 2015年 杨振. All rights reserved.
//

import UIKit

/**
1. Emoticons.bundle的根目录中有一个 emoticons.plist
   packages数组的每一项字典中的 id 对应的是每一套表情的目录名
2. 每一个表情目录下，都有一个 info.plist 文件
   group_name_cn 记录的表情包的名字
   emoticons 数组，记录的整套表情的数组
3. 表情字典信息
   chs:    定义的发布微博以及网络传输使用的微博文字字符串
   png:    在客户端显示的图片名称

   code:   emoji要显示的16进制字符串！
*/
/// 表情包模型 - 从 emoticons.plist 加载
class EmoticonPackage: NSObject {

    /// 目录名
    var id: String
    /// 分组名
    var groupName: String = ""
    /// 创建 表情数组 （并没有初始化）
    var emoticons: [Emoticon]?
    init(id: String, groupName: String = "") {
        self.id = id
        self.groupName = groupName
    }
    /// 加载所有的：表情包 - 通过类函数 计算行属性 保存有多少组：packages （每组有什么内容：emoticons）
    class func packages() -> [EmoticonPackage] {
        // 1.加载路径
        let path = bundlePath.stringByAppendingString("/emoticons.plist")
        
        // 2.从路径中加载plist数据  
        let dict = NSDictionary(contentsOfFile: path)!
        let array = dict["packages"] as! [[String: AnyObject]]
        
        // 3.遍历数组   （实例化模型属性：）
        var arrM = [EmoticonPackage]()
        
        // !!!开始遍历表情包数组之前，最佳空白按钮分组
        let package = EmoticonPackage(id: "", groupName: "最近").appendEmptyEmoticons()
        arrM.append(package)
        
        
        for dict in array {
            let id = dict["id"] as! String
            // MARK: - 链式响应 swift 特有的
            // 1.根据对应的id 取出对应的表情包的组
            // 2.使用链式响应进一步获取emoticons中的模型
            // 3.再追加emoticons模型时 使用KVC 获取内部的属性
            // 4.如果不够一页最佳空白表情，继续最佳到emoticons 返回值：self
            let package = EmoticonPackage(id: id).loadEmoticon().appendEmptyEmoticons()
            arrM .append(package)
        }
        return arrM
    }
    
    /// 加载当前对象对应的表情数组，从 info.plist 中加载并完成完整的模型信息
    /// Self 表示返回本类的对象
    func loadEmoticon() -> Self {
        // 1. 获取每个图库的路径
        let path = EmoticonPackage.bundlePath.stringByAppendingString("/" + id).stringByAppendingString("/info.plist")
        // 2. 根据路径中的plist 获取其中的字典
        let dict = NSDictionary(contentsOfFile: path)!
        
        // TODO: groupName的哟用处？？
        groupName = dict["group_name_cn"] as! String
        let array = dict["emoticons"] as! [[String: String]]
        
        // 遍历数组
        emoticons = [Emoticon]()
        var index = 0
        for dict in array {
            emoticons?.append(Emoticon(id: id, dict: dict))

            index++
            if index == 20 {
                emoticons?.append(Emoticon(remove: true))
                index = 0
            }
            
        }
        return self
    }
    /// 在表情数组中追加空白表情 - 如果最后一页不是 21 个表情，追加空白表情，并且最后一个放删除按钮
    func appendEmptyEmoticons() -> Self {
    
        // 判断表情是否存在 若果为空则创建一个新的表情分组模型
        if emoticons == nil {
            emoticons = [Emoticon]()
        }
        
        let count = emoticons!.count % 21
        print("已经有\(count)个表情")
        
        if count > 0 || emoticons!.count == 0 {
            for _ in count..<20 {
                // 不足20个表情 我就将此处的模型按钮标记为 删除标记
                emoticons?.append(Emoticon(remove: false))
            }
            // 否则标记在末尾处追加一个按钮 此处的按钮数据不用移除
            emoticons?.append(Emoticon(remove: true))
        }
        return self
    }
    
    // 加载路径 使用static修饰就可以全局访问到了
    static let bundlePath = NSBundle.mainBundle().bundlePath.stringByAppendingString("/Emoticons.bundle")
    // 析构函数：description
    override var description: String {
        return "\(id), \(groupName), \(emoticons)"
    }
}
/// 表情模型
class Emoticon: NSObject {

    /// 表情目录
    var id: String?
    /// 发送给服务器的表情文字
    var chs: String?
    /// 本地显示的图片文件名
    var png: String?
    /// 完整的图片路径
    var imagePath: String {
        // 如果发送给服务器的表情文字为nil 者返回一个 ""
        if chs == nil {
            return ""
        }
        // bundlePath + id + png
        return EmoticonPackage.bundlePath.stringByAppendingString("/" + id!).stringByAppendingString("/" + png!)
    }
    /// emoji 的代码
    var code: String? {
        didSet {
            // 扫描器
            let scanner = NSScanner(string: code!)
            
            var value: UInt32 = 0
            scanner.scanHexInt(&value)
            
            emoji = String(Character(UnicodeScalar(value)))
        }
    }
    // emoji 字符串
    var emoji: String?
    // 添加删除按钮
    var removeEmoticon = false
    init(remove: Bool) {
        removeEmoticon = remove
    }
    
    
    // 外界当调用此方法的时候，给我传递一个id 
    // 我就用本类中新定义的id 进行接收以下方便本类中的其他方法调用
    init(id: String, dict: [String: String]) {
       // 接收外界传过来的参数，给本类的id属性进行赋值 方便本类获取外界传过来的 id
        self.id = id
        
        super.init()
        // 会根据 字典中的 值对 顺序调用 setValueForKey(key存在)
        setValuesForKeysWithDictionary(dict)
    }
    
    override func setValue(value: AnyObject?, forKey key: String) {
//        print("KVC 设置属性")
        super.setValue(value, forKey: key)
    }
    
    override func setValue(value: AnyObject?, forUndefinedKey key: String) {}
    
    // 析构函数：description
    override var description: String {
        return "\(id), \(chs), \(png), \(removeEmoticon)"
    }
    
}



